package com.yukefms.rule.state;

import com.yukefms.engine.running.EventCode;
import com.yukefms.engine.running.RunningContext;
import com.yukefms.jointpoint.BodyPointCloud;
import com.yukefms.rule.interfaces.BARule;
import com.yukefms.rule.interfaces.BAStageRule;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @Description
 * @Author Ping
 * @Date 2021/7/17 8:43
 **/

/**
 * needs to update .
 */
public class WrongPerformingState extends ActivatedState {
    public static Logger logger = LogManager.getLogger(WrongPerformingState.class);

    public WrongPerformingState(final BAStageRule relatedRule) {
        super(relatedRule);
    }

    /**
     *  * WRONG_PERFORM  -- Response                  -->  PARTIAL_MATCHED (SCORE(PARTIAL))
     *  * WRONG_PERFORM  -- NOT Dynamic               -->  UN_MATCHED (SCORE(triggered))
     *  * WRONG_PERFORM  -- Dynamic                   -->  WRONG_PERFORM
     *  * UN_MATCHED     --   trial_out               -->     FAILED
     *  * PARTIAL_MATCHED    -- trial_out             -->     FAILED
     * @param pointCloud
     * @param context
     */
    @Override
    protected void processRelevantPointsCloud(BodyPointCloud pointCloud, RunningContext context) {
        context.updateCachingPointCloud(pointCloud);
        if (! this.relatedRule.isPerforming(pointCloud, context)) {
            // tolereant for not performing
            context.updatePerformingFailCounter();
            if (context.getPerformingFailCounter().isOverMax()) {
                logger.error("The performing formula of RULE-{} is NOT SATISFIED since perform fail overtime and transitioned to unmatched"
                        , this.relatedRule.currentStage().getName());
                context.notifyRunningEventListener(EventCode.UNMATCHED, relatedRule.currentStage().getName());
                context.getPerformingFailCounter().reset();
                context.getInvariantFailCounter().reset();
                this.relatedRule.setRuleState(RuleStateFlyWeight.getState(RuleStateFlyWeight.UN_MATCHED));
                this.relatedRule.doReaction(pointCloud, context);
            }
        } else {

            if (this.relatedRule.responseArrived(pointCloud, context)) {
                if (! this.relatedRule.hasNextStage()) {
                    /**
                     * if not more stage to be finished, then transtion to PARTIAL_MATCH state.
                     */
                    context.notifyRunningEventListener(EventCode.PARTIAL_MATCHED, this.relatedRule.currentStage().getName());
                    logger.error("the Rule-{} is PARTIAL_MATCH for current point cloud.", this.relatedRule.ruleName());
                    context.getPerformingFailCounter().reset();
                    context.getInvariantFailCounter().reset();
                    this.relatedRule.setRuleState(RuleStateFlyWeight.getState(RuleStateFlyWeight.PARTIAL_MATCHED));
                    this.relatedRule.doReaction(pointCloud, context);
                    context.updateScore(relatedRule.currentStage().getScore());
                } else {
                    /**
                     * to the next stage with new dyanmic and response.
                     */
                    context.notifyRunningEventListener(EventCode.PARTIAL_MATCHED, this.relatedRule.currentStage().getName());
                    logger.error("the Rule-{} is finished uncorrectly stage {} for current point cloud.",
                            this.relatedRule.ruleName(), this.relatedRule.currentStage().getName());
                    context.updateScore(relatedRule.currentStage().getScore());
                    this.relatedRule.toNextStage();
                }
            }
            /**
             * else part: stay in the WrongPerformingState and
             * cache current pointCloud.
             */


        }
    }

}
